package mao.thinkinjava.io;

import java.io.*;
import java.nio.IntBuffer;
import java.nio.channels.FileChannel;


/**
 *randomAccessFile是不删除原文件，打开，但是开始的文件指针在开头
 * Stream write
 * 0.02
 * Stream read
 * 0.02
 * Mapped IO write
 * 800000
 * 0.01
 * Map IO read
 * 800000
 * 0.01
 * stream read/write   随机访问，所以不能加buffer所以速度很慢。
 * 17.00
 * Map io read/write
 * 1599996
 * 0.01
 * 随机访问很消耗IO时间
 */

public class MappedIO {
    private static int numOfInts = 200000;
    private static int numOfUnbuffInts = 200000;
    private static abstract class Tester {
        private String name ;
        Tester(String name){
            this.name = name;
        }
        public void runTest() {
            System.out.println(name);
            long start = System.nanoTime();
            try {
                test();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            long end = System.nanoTime();
            System.out.format("%.2f\n",(end-start)/1.0e9); //以秒为单位。
        }
        public abstract void test() throws IOException;
    }
    private static Tester[] testers = {
            new Tester("Stream write") {
                @Override
                public void test() throws IOException{
                    DataOutputStream out;
                    out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("temp.tmp")));
                    for (int i = 0; i < numOfInts; i++) {
                        out.writeInt(i);
                    }
                    out.close();
                }
            },
            new Tester("Stream read") {
                @Override
                public void test() throws IOException {
                    DataInputStream in;
                    in = new DataInputStream(new BufferedInputStream(new FileInputStream("temp.tmp")));
                    for (int i = 0; i < numOfInts; i++) {
                        in.readInt();
                    }
                    in.close();
                }
            },
            new Tester("Mapped IO write") {
                @Override
                public void test() throws IOException {
                    //Mapmode.没有WRITE_ONLY
                    FileChannel fc = new RandomAccessFile("temp.tmp", "rw").getChannel();
                    System.out.println(fc.size());
                    IntBuffer intBuffer = fc.map(FileChannel.MapMode.READ_WRITE, 0,fc.size()).asIntBuffer();
                    for (int i = 0; i < numOfInts; i++) {
                        intBuffer.get(i);
                    }
                    fc.close();
                }
            },
            new Tester("Map IO read") {
                @Override
                public void test() throws IOException {
                    FileChannel fc = new FileInputStream("temp.tmp").getChannel();
                    System.out.println(fc.size());
                    IntBuffer intBuffer = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()).asIntBuffer();
                    for (int i = 0; i < numOfInts; i++) {
                        intBuffer.get(i);
                    }
                    fc.close();
                }
            },
            new Tester("stream read/write") {
                @Override
                public void test() throws IOException {
                    //没有buffer，随机访问呢，也没有buffer
                    RandomAccessFile rw = new RandomAccessFile("temp.tmp", "rw");
                    rw.seek(0);
                    rw.writeInt(0);
                    for (int i = 1; i < numOfUnbuffInts; i++) {
                        rw.seek((i-1)*4);
                        rw.writeInt(rw.readInt());
                    }
                    rw.close();
                }
            },
            new Tester("Map io read/write") {
                @Override
                public void test() throws IOException {
                    FileChannel fc = new RandomAccessFile("temp.tmp", "rw").getChannel();
                    System.out.println(fc.size());
                    IntBuffer ib = fc.map(FileChannel.MapMode.READ_WRITE, 0, fc.size()).asIntBuffer();
                    ib.put(0);
                    for (int i = 1; i < numOfUnbuffInts; i++) {
                       ib.put(ib.get(i-1));
                    }
                    fc.close();
                }
            }
    };

    public static void main(String[] args) {
        for (Tester t:testers){
            t.runTest();
        }
    }
}
